package com.wn.search

import android.content.Context
import android.content.Intent
import androidx.activity.viewModels
import androidx.core.view.isVisible
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.LinearLayoutManager
import com.blankj.utilcode.util.ConvertUtils
import com.blankj.utilcode.util.ToastUtils
import com.scwang.smart.refresh.layout.api.RefreshLayout
import com.scwang.smart.refresh.layout.listener.OnLoadMoreListener
import com.wn.common.dialog.MessageDialog
import com.wn.common.model.ArticleList
import com.wn.common.model.HotSearch
import com.wn.common.provider.LoginServiceProvider
import com.wn.common.provider.UserServiceProvider
import com.wn.framework.base.BaseActivity
import com.wn.framework.ext.onClick
import com.wn.framework.ext.textChangeFlow
import com.wn.framework.utils.StatusBarSettingHelper
import com.wn.framework.utils.ViewUtils.setClipViewCornerRadius
import com.wn.search.adapter.SearchResultAdapter
import com.wn.search.databinding.ActivitySearchBinding
import com.wn.search.utils.SearchManager
import com.wn.search.viewmodel.SearchViewModel
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import javax.inject.Inject

/**
 * @Author: wn
 * @Date: 2024/12/11 15:48
 * @Description: 搜索页面
 */
@AndroidEntryPoint
class SearchActivity : BaseActivity<ActivitySearchBinding>(), OnLoadMoreListener {

  override fun getLayoutRes() = R.layout.activity_search

  private val viewModel by viewModels<SearchViewModel>()

  @Inject
  lateinit var mAdapter: SearchResultAdapter

  private var page = 0

  /**
   * 搜索标签 item 点击
   * textChangeFlow 会触发搜索 -- getSearchResult()
   */
  private val clickCallBack = { keyWord: String ->
    page = 0
    mBinding.etSearch.setText(keyWord)
  }

  override fun initView() {
    super.initView()
    StatusBarSettingHelper.setStatusBarTranslucent(this)
    StatusBarSettingHelper.statusBarLightMode(this, true)
    mBinding.apply {
      setClipViewCornerRadius(etSearch, ConvertUtils.dp2px(6.0F))
      setClipViewCornerRadius(tvSearch, ConvertUtils.dp2px(4.0F))
      setClipViewCornerRadius(viewSearchHistory, ConvertUtils.dp2px(14.0F))
      setClipViewCornerRadius(clSearchResult, ConvertUtils.dp2px(14.0F))
    }
    initRecyclerView()
    initListener()
  }

  private lateinit var job: Job
  override fun initData() {
    // 再次进入初始化的时候 展示历史记录
    setSearchHistory()

    if (::job.isInitialized) job.cancel()
    job = lifecycleScope.launch {
      lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
        // 搜索热词
        launch {
          viewModel.getHotSearchData().collect {
            it ?: return@collect
            initSearchRecommend(it)
          }
        }
        // 加载 loading
        launch {
          // delay(20) // 确保 loading 先为 true-->控制 刷新
          viewModel.loading.collect {
            if (it) showLoading() else dismissLoading()
          }
        }
      }
    }
  }

  private fun initRecyclerView() {
    mBinding.apply {
      refreshLayout.apply {
        autoRefresh()
        setEnableRefresh(false)
        setEnableLoadMore(true)
        setOnLoadMoreListener(this@SearchActivity)
      }

      recyclerView.apply {
        layoutManager = LinearLayoutManager(this@SearchActivity)
        adapter = mAdapter
      }
    }
    mAdapter.onClickCollect = { position, item ->
      /**
       * 登录后 收藏文章
       * 未登录 -- 跳转登录页
       */
      if (UserServiceProvider.isLogin()) {
        collectArticle(position, item)
      } else {
        LoginServiceProvider.toLogin(this@SearchActivity)
      }
    }
  }

  @OptIn(FlowPreview::class, ExperimentalCoroutinesApi::class)
  private fun initListener() {
    mBinding.apply {
      // 返回按钮
      searchBack.onClick {
        finish()
      }
      // 搜索按钮
      tvSearch.onClick {
        if (mBinding.etSearch.text.toString().isEmpty()) return@onClick
        page = 0
        // 搜索数据
        getSearchResult()
      }
      /**
       * 边输入 边进行搜索 ，所以取代 addTextChangedListener + setOnEditorActionListener
       * 进行防抖处理
       * launchIn 一般搭配 onEach 一起使用 ,
       */
      mBinding.etSearch.textChangeFlow()
        .filter { it.isNotEmpty() }
        .debounce(600)
        .onEach {
          /**
           * 1 此时 it不为空 显示 搜索结果 UI
           */
          withContext(Dispatchers.Main) {
            initSearchUI(it)
          }
        }
        .flatMapLatest {
          /**
           * 2 网络请求
           */
          viewModel.searchResult(page, it)
        }
        .flowOn(Dispatchers.IO)
        .onEach {
          /**
           * 3 更新 列表
           */
          initSearchResult(it)
        }
        .launchIn(lifecycleScope)
/*
      // 编辑框输入文字 展示 UI
      etSearch.addTextChangedListener {
        clSearchResult.isVisible = it.toString().isNotEmpty()
      }
      // 该监听是 操作 软键盘触发 这里是 点击搜索按钮
      etSearch.setOnEditorActionListener { _, id, _ ->
        if (id == EditorInfo.IME_ACTION_SEARCH) getSearchResult()
        return@setOnEditorActionListener false
      }

      */

      // 点击标签
      viewSearchRecommend.setOnCheckChangeListener(clickCallBack)
      viewSearchHistory.setOnCheckChangeListener(clickCallBack)
      // 叉号点击 触发 { } --> 触发弹框 --> 确认 --> 触发 lambda 的参数 it的执行
      viewSearchHistory.setOnHistoryClearListener {
        clearHistoryCache(it)
      }
    }
  }

  /**
   * 设置搜索历史 -- 标签列表
   */
  private fun setSearchHistory() {
    val list = SearchManager.getSearchHistory()?.reversed()?.toMutableList()
    mBinding.viewSearchHistory.setHistoryData(list)
  }

  /**
   * 点击时才会触发
   * 不同的搜索结果 展示
   */
  private lateinit var jobSearch: Job
  private fun getSearchResult() {
    val keyWord = mBinding.etSearch.text.toString()

    initSearchUI(keyWord)

    if (::jobSearch.isInitialized) jobSearch.cancel()
    jobSearch = lifecycleScope.launch {
      lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
        // 历史搜索结果
        viewModel.searchResult(page, keyWord).collect {
          initSearchResult(it)
        }
      }
    }
  }

  /**
   * 初始化 搜索热词
   * @param datas MutableList<String>
   */
  private fun initSearchRecommend(datas: MutableList<HotSearch>) {
    val list = datas.map { it.name ?: "" }.toMutableList()
    mBinding.viewSearchRecommend.apply {
      setHistoryData(list)
      // 取消 删除按钮
      getDeleteImageView().isVisible = false
    }
  }

  /**
   * 获取数据后 UI 的 更新
   * @param data ArticleList
   */
  private fun initSearchResult(data: ArticleList?) {
    if (page == 0) {
      mBinding.viewEmptyData.isVisible = data?.datas.isNullOrEmpty()
      data ?: return
      mAdapter.setData(data.datas)
    } else {
      mAdapter.addData(data?.datas)
      mBinding.refreshLayout.finishLoadMore()
    }
  }

  /**
   * 初始化搜索 UI
   * @param keyWord String
   */
  private fun initSearchUI(keyWord: String) {
    if (page == 0 && keyWord.isNotEmpty()) {
      // MMKV 添加搜索记录
      SearchManager.addSearchHistory(keyWord)
      // 展示 搜索记录
      setSearchHistory()
      // 点击标签时 展示 UI  
      mBinding.clSearchResult.isVisible = true
      mBinding.viewEmptyData.isVisible = true
    }
  }

  /**
   * 清除搜索历史
   */
  private fun clearHistoryCache(clearSuccess: () -> Unit) {
    MessageDialog.Builder(this)
      .setTitle(getString(com.wn.framework.R.string.dialog_tips_title))
      .setMessage(getString(com.wn.framework.R.string.search_clear_history))
      .setConfirm(getString(com.wn.framework.R.string.default_confirm))
      .setConfirmTxtColor(getColor(com.wn.framework.R.color.color_0165b8))
      .setCancel(getString(com.wn.framework.R.string.default_cancel))
      .setonCancelListener {
        it?.dismiss()
      }
      .setonConfirmListener {
        SearchManager.clearSearchHistory()
        clearSuccess.invoke() // SearchHistoryView 清除标签
        it?.dismiss()
      }
      .create()
      .show()
  }

  override fun onLoadMore(refreshLayout: RefreshLayout) {
    page++
    getSearchResult()
  }

  private lateinit var jobCollect: Job

  /**
   * 收藏 or 取消收藏          -- adapter 更新某一个位置上的数据
   * @param position Int     -- 位置
   * @param item Item        -- 数据
   */
  private fun collectArticle(position: Int, item: ArticleList.ArticleInfo) {
    if (::jobCollect.isInitialized) jobCollect.cancel()
    jobCollect = lifecycleScope.launch {
      lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
        // 收藏 or 取消收藏
        val collect = item.collect ?: false
        viewModel.collectArticle(item.id ?: 0, collect).collect {
          // 这里根据点击之前的 collect 状态来判断是收藏还是取消收藏  -- true 表示要取消 ,false 表示要收藏
          val tipsRes =
            if (collect) com.wn.framework.R.string.collect_cancel else com.wn.framework.R.string.collect_success
          ToastUtils.showShort(tipsRes)
          /**
           * 更改 item 的 collect 状态 取反
           * 更新某一个位置上的数据
           */
          item.collect = !collect
          mAdapter.updateItem(position, item)
        }
      }
    }
  }

  /**
   * Home键或者锁屏 后 如果不 cancel 返回时数据会重复请求  -- stop
   * viewPager 滑动 -- pause
   */
  override fun onStop() {
    if (::job.isInitialized) job.cancel()
    if (::jobSearch.isInitialized) jobSearch.cancel()
    if (::jobCollect.isInitialized) jobCollect.cancel()
    super.onStop()
  }

  companion object {
    fun start(context: Context) {
      val intent = Intent(context, SearchActivity::class.java)
      context.startActivity(intent)
    }
  }
}